package com.strange3.multiplemodulespreloader
{
	
	import com.strange3.utils.modules.ModuleCreatorsManager;
	import com.strange3.utils.modules.ModuleLoadableContentCreator;
	import com.strange3.utils.modules.treepreloader.ITreePreloader;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;

	public class TreePreloader extends EventDispatcher implements ITreePreloader
	{
		public static const contenLoaded:String = "contentLoaded";
		
		// manager do przechowywania i pozyskiwania wszyskich modulow dodanych do drzewa
		protected var _moduleCreatorsManager:ModuleCreatorsManager;
		
		// tablica z obiektami typu batchpreloader
		protected var _preloaders:Array;
		
		// zmienna przechowująca numer ostatnio załadowanego poziomu modułów
		private var _lastLoadedIndex:int;
		
		// variable holds all loaded modules in full batches
		protected var _modulesLoaded:Array;
		
		public function TreePreloader()		{
			_preloaders = new Array();
			this._modulesLoaded = new Array();	
			this._lastLoadedIndex = 0;
			this._moduleCreatorsManager = new ModuleCreatorsManager();
		}
		
		/**
		 * Zwracamy managera modulow zawartych w preloaderze 
		 * @return 
		 * 
		 */
		public function get modulesManager():ModuleCreatorsManager {
			return this._moduleCreatorsManager;
		}

		public function addModule(m:ModuleLoadableContentCreator, weight:int):void {
			
			// waga modułu, to jest indeks w naszej tablicy preloaderów
			// jeśli tablica od tego elementu jeszce nie została zainicjalizowana
			// to musimy to zrobić
			if(!_preloaders[weight]) {
				_preloaders[weight] = new BatchPreloader();
			}
			
			// dodajemy do grupowego preloadera pod tym indeksem moduł 
			(_preloaders[weight] as BatchPreloader).addModule(m);
			
			// dodajemy modul do managera
			_moduleCreatorsManager.add(m);
		}
		
		public function load():void	{
			// jesli jest to pierwsze wywolanie funkcji to mamy
			// index _lastLoadedIndex ustawiony na zero, wiec sprawdzamy
			// od poczatu tablicy z batchpreloaderami, ktry ma jakas zawartosc
				
			// czy ten element w tablicy posiada jakiś preloader i czy ostanie 
			// wywoalnie tej funkcjo nie obsluzylo juz ostatniego elementu z tablicy ?
			if((_lastLoadedIndex < _preloaders.length) && this._preloaders[this._lastLoadedIndex]) {
				
				// tak, pod tym elemente w talicy preloaderów znajduje sie obiekt 
				// wysylamy do niego prosbe o zaladowanie zawartosci
				(this._preloaders[this._lastLoadedIndex] as BatchPreloader).load();	
							
				// i nasluchuujemy zakoncenia tego zdarzenia				
				(this._preloaders[this._lastLoadedIndex] as BatchPreloader).addEventListener(BatchPreloader.batchLoaded, onBatchLoaded);
				
				// zwiekaszmy indeks ostaniego ladowanego elementu o jeden
				this._lastLoadedIndex++;
			} else {
				
				// czyli nie bylo zadnego elementu do preloadowania pod tym indeksem
				// jesli wiec nie jest to przypadkiem koniec tablicy, to sprawdzamy
				// nastepny element
				if(this._lastLoadedIndex<this._preloaders.length) {
					this._lastLoadedIndex++;
					this.load();	
				}
			}
			
		}
		
		/**
		 * Get all loaded modules 
		 * @return 
		 * 
		 */
		public function get loadedModules():Array {
			return this._modulesLoaded;
		}
		
		/**
		 * Funkcja wywoływana gdy jedna paczka preloeaderów
		 * zostanie załadowana 
		 * @param e
		 * 
		 */
		private function onBatchLoaded(e:Event):void {
			
			// save reference to loaded batch
			var loadedBatch:BatchPreloader = (e.target as BatchPreloader);
			 
			// nie będziemy potrzebować już tego listenera
			loadedBatch.removeEventListener(BatchPreloader.batchLoaded, onBatchLoaded);
			
			// we're adding modules from this batch to list of all modules loaded
			this._modulesLoaded.concat(loadedBatch.loadedModules);
			
			// sprawdzamy czy nie załadowaliśmy własnie ostaniej paczki modułów
			if(this._lastLoadedIndex == this._preloaders.length) {
				
				// tak, wysyłamy informację w eventcie
				this.dispatchEvent(new Event(TreePreloader.contenLoaded));
			} else {
				
				// nie, mamy jeszcze moduły do załadowania w paczkach
				this.load();
			}
		}
	}
	

}